home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 May: Tool Chest / Developer CD Series May 1996 (Tool Chest) (Apple Computer) (1996).iso / Sample Code / Snippets / Networking / TalkTool / Talk.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-05-18  |  19.1 KB  |  857 lines  |  [TEXT/MPS ]

  1. #include <Stdio.h>
  2. #include <Memory.h>
  3. #include <Types.h>
  4. #include <CursorCtl.h>
  5. #include <AppleTalk.h>
  6. #include <Packages.h>
  7. #include <Events.h>
  8. #include <SysEqu.h>
  9. #include <Desk.h>
  10. #include <Devices.h>
  11. #include <Errors.h>
  12.  
  13. /*
  14.                     © Copyright 1989 Apple Computer, Inc.
  15.  
  16.     This is an MPW 3.0 tool to demonstrate how AppleTalk calls are implemented in MPW C 3.0
  17.     and assembler 3.0.
  18.     AppleTalk protocols shown are:
  19.     
  20.         NBP
  21.         DDP
  22.         Echo
  23.         ATP
  24.         ZIP
  25.     
  26.         
  27.     The functions we provide here are:
  28.     
  29.         Register a name in the network, the user provides an object name and a type,
  30.         the tool provides a dummy socket listener so the socket does not get reused
  31.         by another process.
  32.         
  33.         Lookup names in the network, the user can optionally give as parameters an
  34.         object name, a type name, a zone or a combination of the three as search
  35.         criteria.  Initial buffer allocated is for 200 names.
  36.         
  37.         Write a DDP packet.  The user provides a destination network number,
  38.         destination node, socket, ddpType and optional data.  Before sending
  39.         a ddp packet a socket is opened and a socket listener installed in case
  40.         we receive a response, then the packet is sent out and we wait 30
  41.         seconds for a response.  If a response is received then we display the
  42.         data we got.
  43.         The socket and its listener are then disposed of.
  44.         
  45.         Write an ATP packet.  The user provides a destination network number,
  46.         destination node, socket, atpUserData and optional data.  The packet
  47.         is sent out as a transaction request and we wait 30 seconds for a response.
  48.         If a response is received then we display the data we got back.
  49.         
  50.         Write an Echo packet.  The user provides a destination network number,
  51.         destination node, and optional data.  To send an Echo packet we first
  52.         create a ddp socket and a socket listener to receive the echo reply.
  53.         The packet is sent out and we wait 30 seconds for the echo reply.
  54.         If a reply is received then we display the data we got.
  55.         The ddp socket and its listener are then disposed of.
  56.     
  57.         Set SelfSend flag.  This enables or disables the capability to send
  58.         and receive packets from our own machine.
  59.         
  60.         Zone names can be requested from the network, and the zone to which
  61.         this machine belongs is pointed out to the user.
  62.         
  63.         
  64.         NOTE:  THIS TOOL IS NOT FULLY COMMENTED BECAUSE A NEW VERSION WILL BE
  65.         IMPLEMENTED IN C++
  66.         
  67.         
  68.     Written by Ricardo Batista. 1/12/89
  69. */
  70.  
  71. #define    Buf    20000
  72. #define        TRUE        -1
  73. #define        FALSE        0
  74.  
  75.  
  76. #define        GetZoneList        0x8000000
  77. #define        GetMyZone        0x7000000
  78.  
  79.  
  80. pascal void InitDDPListener(ATDDPRec *ddp);
  81. pascal void DDPListener(void);
  82.  
  83.  
  84.  
  85.  
  86. typedef struct {
  87.     short moveq0_d3;
  88.     long jmp2_a4;
  89. } dumb_listener;
  90.  
  91.  
  92.  
  93.  
  94. void DoDDP(int argc, char* argv[], Boolean echo);
  95. Boolean Abort(void);
  96. void SetSelf(char* argv[]);
  97. void Usage(char* argv[]);
  98. void Names(int argc, char* argv[]);
  99. void DoATP(int argc, char* argv[]);
  100. void DoRegName(int argc, char* argv[]);
  101. void DoZones(char* argv[]);
  102.  
  103. short mpp;
  104.  
  105.  
  106. int main(int argc, char* argv[])
  107. {
  108.     short err;
  109.     char *copyright = {"© 1989 Apple Computer, Inc.  By Ricardo Batista"};
  110.     // short counter;
  111.     
  112.     // fprintf(stdout,"argc = %d\n",argc);
  113.     // for (counter = 0; counter < argc; counter++)
  114.         // fprintf(stdout,"argv[%d] = %s\n",counter,argv[counter]);
  115.     // fflush(stdout);
  116.     if (argc < 2) {
  117.         Usage(argv);
  118.         return(1);
  119.     }
  120.     InitCursorCtl(0L);
  121.     SpinCursor(1);
  122.     err = OpenDriver("\p.MPP",&mpp);
  123.     if (err) {
  124.         fprintf(stderr,"## %s: Error opening AppleTalk %d\n",argv[0],err);
  125.         return(1);
  126.     }
  127.     SpinCursor(1);
  128.     if ((argv[1][0] == '-') && ((argv[1][1] == 'n') || (argv[1][1] == 'N'))) {
  129.         Names(argc, argv);
  130.     }
  131.     if ((argv[1][0] == '-') && ((argv[1][1] == 'r') || (argv[1][1] == 'R'))) {
  132.         if (argc != 6) {
  133.             Usage(argv);
  134.             return(1);
  135.         }
  136.         DoRegName(argc, argv);
  137.     }
  138.     if ((argv[1][0] == '-') && ((argv[1][1] == 's') || (argv[1][1] == 'S'))) {
  139.         if (argc != 3) {
  140.             Usage(argv);
  141.             return(1);
  142.         }
  143.         SetSelf(argv);
  144.     }
  145.     if ((argv[1][0] == '-') && ((argv[1][1] == 'd') || (argv[1][1] == 'D'))) {
  146.         if (argc < 6) {
  147.             Usage(argv);
  148.             return(1);
  149.         }
  150.         DoDDP(argc, argv, false);
  151.     }
  152.     if ((argv[1][0] == '-') && ((argv[1][1] == 'e') || (argv[1][1] == 'E'))) {
  153.         if (argc < 3) {
  154.             Usage(argv);
  155.             return(1);
  156.         }
  157.         DoDDP(argc, argv, true);
  158.     }
  159.     if ((argv[1][0] == '-') && ((argv[1][1] == 'a') || (argv[1][1] == 'A'))) {
  160.         if (argc < 6) {
  161.             Usage(argv);
  162.             return(1);
  163.         }
  164.         DoATP(argc, argv);
  165.     }
  166.     if ((argv[1][0] == '-') && ((argv[1][1] == 'z') || (argv[1][1] == 'Z'))) {
  167.         if (argc < 1) {
  168.             Usage(argv);
  169.             return(1);
  170.         }
  171.         DoZones(argv);
  172.     }
  173.     return(0);
  174. }
  175.  
  176.  
  177.  
  178.  
  179.  
  180.  
  181.  
  182.  
  183.  
  184.  
  185.  
  186.  
  187.  
  188.  
  189. void DoRegName(int argc, char* argv[])
  190. {
  191.     EntityName name;
  192.     short err, counter, len;
  193.     THz zone;
  194.     MPPParamBlock p;
  195.     NamesTableEntry *NTPtr;
  196.     short index;
  197.     unsigned char socket;
  198.     dumb_listener *listener;
  199.     
  200.     SpinCursor(1);
  201.     zone = GetZone();
  202.     SetZone(SystemZone());
  203.     listener = (dumb_listener*) NewPtr(sizeof(dumb_listener));
  204.     SetZone(zone);
  205.     if (!listener) {
  206.         fprintf(stderr,"## %s: Error getting space for socket listener\n\n",argv[0]);
  207.         return;
  208.     }
  209.     listener->moveq0_d3 = 0x7600;
  210.     listener->jmp2_a4 = 0x4EEC0002;
  211.     p.MPPioCompletion = 0L;
  212.     p.MPPioRefNum = mpp;
  213.     p.DDPsocket = 0;
  214.     p.DDPlistener = (Ptr) listener;
  215.     err = POpenSkt(&p,FALSE);
  216.     socket = p.DDPsocket;
  217.     if (err) {
  218.         fprintf(stderr,"## %s: Error opening socket %d\n\n",argv[0],err);
  219.         return;
  220.     }
  221.     if (!socket) {
  222.         fprintf(stderr,"## %s: Could not open socket, socket = %d, err = %d\n",argv[0],(short) socket,err);
  223.         return;
  224.     }
  225.     name.objStr[1] = 0;
  226.     name.typeStr[1] = 0;
  227.     name.zoneStr[1] = 0;
  228.     name.objStr[0] = '=';
  229.     name.typeStr[0] = '=';
  230.     name.zoneStr[0] = '*';
  231.     for (counter = 2; counter < argc; counter++) {
  232.         if (argv[counter][0] == '-') {
  233.             if ((argv[counter][1] == 'o') || (argv[counter][1] == 'O')) {
  234.                 BlockMove(argv[counter + 1],name.objStr,33L);
  235.             }
  236.             if ((argv[counter][1] == 't') || (argv[counter][1] == 'T')) {
  237.                 BlockMove(argv[counter + 1],name.typeStr,33L);
  238.             }
  239.         }
  240.     }
  241.     len = sizeof(NamesTableEntry);
  242.     if ((name.typeStr[0] == '=') || (name.objStr[0] == '=')) {
  243.         fprintf(stderr,"## %s: Object and type names must not be any of '@ * = :'\n",argv[0]);
  244.         return;
  245.     }
  246.     zone = GetZone();
  247.     SetZone(SystemZone());
  248.     NTPtr = (NamesTableEntry*) NewPtr(len);
  249.     SetZone(zone);
  250.     if (!NTPtr) {
  251.         fprintf(stderr,"## %s: Not enough memory.\n",argv[0]);
  252.         return;
  253.     }
  254.     NTPtr->nt.nteAddress.aSocket = socket;
  255.     p.NBPinterval = 3;
  256.     p.NBPcount = 3;
  257.     p.NBPverifyFlag = TRUE;
  258.     p.NBPntQElPtr = (Ptr) NTPtr;
  259.     fprintf(stdout,"## %s: Registering: '%s:%s@*'\n\n",argv[0],name.objStr,name.typeStr);
  260.     fflush(stdout);
  261.     c2pstr(name.objStr);
  262.     c2pstr(name.typeStr);
  263.     c2pstr(name.zoneStr);
  264.     BlockMove(name.objStr,&(NTPtr->nt.entityData[0]),33L);
  265.     index = name.objStr[0] + 1;
  266.     BlockMove(name.typeStr,&(NTPtr->nt.entityData[index]),33L);
  267.     index += name.typeStr[0] + 1;
  268.     BlockMove(name.zoneStr,&(NTPtr->nt.entityData[index]),33L);
  269.     err = PRegisterName(&p,TRUE);
  270.     while ((p.MPPioResult > 0) && !Abort())
  271.             SpinCursor(1);
  272.     err = p.MPPioResult;
  273.     while (err == nbpDuplicate) {
  274.         fprintf(stdout,"## %s: Duplicate name being modified\n",argv[0]);
  275.         fflush(stdout);
  276.         name.objStr[0]++;
  277.         name.objStr[name.objStr[0]] = '1';
  278.         BlockMove(name.objStr,&(NTPtr->nt.entityData[0]),33L);
  279.         index = name.objStr[0] + 1;
  280.         BlockMove(name.typeStr,&(NTPtr->nt.entityData[index]),33L);
  281.         index += name.typeStr[0] + 1;
  282.         BlockMove(name.zoneStr,&(NTPtr->nt.entityData[index]),33L);
  283.         err = PRegisterName(&p,TRUE);
  284.         while ((p.MPPioResult > 0) && !Abort())
  285.             SpinCursor(1);
  286.         err = p.MPPioResult;
  287.     }
  288.     if (err)
  289.         fprintf(stderr,"## %s: err = %d\n",argv[0],err);
  290.     else
  291.         fprintf(stdout,"## %s: Socket %d\n\n",argv[0],(short) socket);
  292. }
  293.  
  294.  
  295.  
  296.  
  297.  
  298.  
  299.  
  300.  
  301.  
  302.  
  303.  
  304.  
  305.  
  306.  
  307.  
  308. void DoATP(int argc, char* argv[])
  309. {
  310.     ATPParamBlock a;
  311.     short err = 0, counter, newline;
  312.     long num;
  313.     Str255 st;
  314.     short len;
  315.     char buffer[578],smallBuffer[5];
  316.     BDSElement bds;
  317.     
  318.     a.ATPioCompletion = 0L;
  319.     a.ATPatpSocket = 0;
  320.     BlockMove(argv[2],st,33L);
  321.     c2pstr(st);
  322.     StringToNum(st,&num);
  323.     a.ATPaddrBlock.aNet = (short) num;
  324.     BlockMove(argv[3],st,33L);
  325.     c2pstr(st);
  326.     StringToNum(st,&num);
  327.     a.ATPaddrBlock.aNode = (short) num;
  328.     BlockMove(argv[4],st,33L);
  329.     c2pstr(st);
  330.     StringToNum(st,&num);
  331.     a.ATPaddrBlock.aSocket = (short) num;
  332.     BlockMove(argv[5],st,33L);
  333.     c2pstr(st);
  334.     StringToNum(st,&num);
  335.     a.ATPuserData = num;
  336.     a.ATPatpFlags = 0;
  337.     a.ATPreqLength = 0;
  338.     a.ATPreqPointer = 0L;
  339.     a.ATPnumOfBuffs = 1;
  340.     a.ATPtimeOutVal = 4;
  341.     a.ATPretryCount = 3;
  342.     a.ATPbdsPointer = (Ptr) &bds;
  343.     bds.buffSize = 600;
  344.     bds.buffPtr = &buffer[0];
  345.     bds.dataSize = 0;
  346.     bds.userBytes = 0L;
  347.     buffer[0] = 0;
  348.     len = 0;
  349.     if (argc > 6) {
  350.         a.ATPreqPointer = argv[6];
  351.         len = strlen(argv[6]);
  352.         fprintf(stdout,"## %s: ATPData to write is %d bytes\n",argv[0],len);
  353.         a.ATPreqLength = len;
  354.     }
  355.     fflush(stdout);
  356.     err = PSendRequest(&a,TRUE);
  357.     while ((a.ATPioResult > 0) && !Abort())
  358.         SpinCursor(1);
  359.     err = a.ATPioResult;
  360.     if (err) {
  361.         if (err == 1)
  362.             PKillSendReq(&a,false);
  363.     }
  364.     if (err)
  365.         fprintf(stderr,"## %s: Error doing ATPRequest %d\n",argv[0],err);
  366.     else {
  367.         fprintf(stdout,"## %s: ATP packet sent, %d ATPData bytes sent.\n",argv[0],len);
  368.         fprintf(stdout,"## %s: Response user data is %ld = '",argv[0],bds.userBytes);
  369.         BlockMove((Ptr) &(bds.userBytes),(Ptr) &smallBuffer[0],4L);
  370.         smallBuffer[4] = 0;
  371.         fprintf(stdout,"%s'\n\n",smallBuffer);
  372.         len = bds.dataSize;
  373.         fprintf(stdout,"## %s: Actual response bytes: %d\n",argv[0],len);
  374.         if (len) {
  375.             for (counter = 0; counter < len; counter++, newline++) {
  376.                 fprintf(stdout,"%c",buffer[counter]);
  377.                 if (buffer[counter] == '\n')
  378.                     newline = 0;
  379.                 if ((newline % 70) == 0)
  380.                     fprintf(stdout,"\n");
  381.             }
  382.         }
  383.     }
  384.     fprintf(stdout,"\n\n");
  385. }
  386.  
  387.  
  388.  
  389.  
  390.  
  391.  
  392.  
  393.  
  394.  
  395.  
  396.  
  397.  
  398.  
  399.  
  400.  
  401.  
  402.  
  403. void DoDDP(int argc, char* argv[], Boolean echo)
  404. {
  405.     MPPParamBlock p;
  406.     short err = 0;
  407.     unsigned char socket = 0;
  408.     long num;
  409.     Str255 st;
  410.     short len, type;
  411.     char buffer[600];
  412.     long ticks;
  413.     int counter;
  414.     WDSElement wds[4];
  415.     AddrBlock address;
  416.     unsigned char header[20];
  417.     ATDDPRec ddp;
  418.     char echoRequest = 1;
  419.     
  420.     ddp.abResult = 1;
  421.     ddp.ddpActCount = 0;
  422.     ddp.ddpReqCount = 586;
  423.     ddp.ddpDataPtr = buffer;
  424.     p.MPPioCompletion = 0L;
  425.     p.MPPioRefNum = mpp;
  426.     p.DDPsocket = 0;
  427.     p.DDPlistener = (Ptr) (ProcPtr) DDPListener;
  428.     err = POpenSkt(&p,FALSE);
  429.     socket = p.DDPsocket;
  430.     if (err) {
  431.         fprintf(stderr,"## %s: Error opening socket %d\n\n",argv[0],err);
  432.         return;
  433.     }
  434.     if (!socket) {
  435.         fprintf(stderr,"## %s: Could not open socket, socket = %d, err = %d\n",argv[0],(short) socket,err);
  436.         return;
  437.     }
  438.     InitDDPListener(&ddp);
  439.     fprintf(stdout,"## %s: Temporary Socket is %d\n",argv[0],(short) socket);
  440.     fflush(stdout);
  441.     BlockMove(argv[2],st,33L);
  442.     c2pstr(st);
  443.     StringToNum(st,&num);
  444.     address.aNet = (short) num;
  445.     BlockMove(argv[3],st,33L);
  446.     c2pstr(st);
  447.     StringToNum(st,&num);
  448.     address.aNode = (short) num;
  449.     len = 0;
  450.     wds[2].entryLength = 0;
  451.     wds[2].entryPtr = 0L;
  452.     wds[3].entryLength = 0;
  453.     wds[3].entryPtr = 0L;
  454.     if (!echo) {
  455.         BlockMove(argv[4],st,33L);
  456.         c2pstr(st);
  457.         StringToNum(st,&num);
  458.         address.aSocket = (short) num;
  459.         BlockMove(argv[5],st,33L);
  460.         c2pstr(st);
  461.         StringToNum(st,&num);
  462.         type = num;                // ddpType to use
  463.         if (argc > 6) {
  464.             len = strlen(argv[6]);
  465.             fprintf(stdout,"## %s: DDPData to write is %d bytes\n",argv[0],len);
  466.         }
  467.         wds[1].entryPtr = argv[6];
  468.         wds[1].entryLength = len;
  469.     }
  470.     else {
  471.         address.aSocket = 4;
  472.         type = 4;
  473.         len = strlen(argv[4]);
  474.         fprintf(stdout,"## %s: Echo protocol data to write is %d bytes\n",argv[0],len);
  475.         wds[1].entryLength = 1;
  476.         wds[1].entryPtr = &echoRequest;
  477.         wds[2].entryLength = len;
  478.         wds[2].entryPtr = argv[4];
  479.     }
  480.     p.MPPioResult = 1;
  481.     p.MPPioCompletion = 0L;
  482.     p.MPPioRefNum = mpp;
  483.     p.DDPchecksumFlag = FALSE;
  484.     p.DDPsocket = socket;
  485.     p.DDPwdsPointer = (Ptr) wds;
  486.     fflush(stdout);
  487.     wds[0].entryPtr = &header[1];
  488.     wds[0].entryLength = 16;
  489.     BlockMove((Ptr) &address.aNet,&header[8],2L);
  490.     header[12] = address.aNode;
  491.     header[14] = address.aSocket;
  492.     header[16] = type;
  493.     err = PWriteDDP(&p,TRUE);
  494.     while ((p.MPPioResult > 0) && !Abort())
  495.         SpinCursor(1);
  496.     if (!err)
  497.         err = p.MPPioResult;
  498.     if (err)
  499.         fprintf(stderr,"## %s: Error doing DDPWrite %d\n",argv[0],err);
  500.     else {
  501.         ticks = TickCount() + 1800;
  502.         fprintf(stdout,"## %s: DDP packet type %d sent, %d DDPData bytes sent.\n",argv[0],type,len);
  503.         fprintf(stdout,"## %s: waiting for a response (30 seconds)...\n",argv[0]);
  504.         fflush(stdout);
  505.         while ((ticks > TickCount()) && (ddp.abResult == 1) && !Abort())
  506.             SpinCursor(1);
  507.         if (ddp.abResult == 0) {
  508.             len = ddp.ddpActCount;
  509.             fprintf(stdout,"## %s: Response received... %d bytes\n",argv[0],len);
  510.             for (counter = 0; counter < len; counter++)
  511.                 fprintf(stdout,"%c",buffer[counter]);
  512.             fprintf(stdout,"\n\n");
  513.         }
  514.         if (ddp.abResult > 0) {
  515.             fprintf(stdout,"## %s: No response...\n",argv[0]);
  516.         }
  517.         if (ddp.abResult < 0)
  518.             fprintf(stdout,"## %s: Error reading a packet id %d...\n",argv[0],ddp.abResult);
  519.     }
  520.     err = PCloseSkt(&p,FALSE);
  521.     if (err)
  522.         fprintf(stderr,"## %s: Error disposing of socket %d\n",argv[0],err);
  523. }
  524.  
  525.  
  526.  
  527.  
  528.  
  529.  
  530.  
  531.  
  532.  
  533.  
  534.  
  535.  
  536.  
  537.  
  538. Boolean Abort(void)
  539. {
  540.     EventRecord myEvent;
  541.     char theChar;
  542.     
  543.     if (EventAvail(keyDownMask,&myEvent)) {
  544.         GetNextEvent(keyDownMask,&myEvent);
  545.         theChar = myEvent.message & charCodeMask;
  546.         if (theChar == '.') {
  547.             if (myEvent.modifiers & cmdKey)
  548.                 return(true);
  549.         }
  550.     }
  551.     return(false);
  552. }
  553.  
  554.  
  555.  
  556.  
  557.  
  558.  
  559.  
  560.  
  561.  
  562.  
  563. void SetSelf(char* argv[])
  564. {
  565.     MPPParamBlock p;
  566.     short err;
  567.     
  568.     p.MPPioCompletion = 0L;
  569.     p.MPPioRefNum = mpp;
  570.     p.SETSELF.newSelfFlag = argv[2][0] - '0';
  571.     err = PSetSelfSend(&p,false);
  572.     if (err)
  573.         fprintf(stderr,"## %s: Error setting SelfSend flag %d",argv[0],err);
  574.     else
  575.         fprintf(stdout,"## %s: Old SelfSend flag is %d\n",argv[0],(short) p.SETSELF.oldSelfFlag);
  576. }
  577.  
  578.  
  579.  
  580.  
  581.  
  582.  
  583.  
  584.  
  585.  
  586.  
  587.  
  588.  
  589.  
  590.  
  591.  
  592. void Usage(char* argv[])
  593. {
  594.     fprintf(stderr,"## %s: No parameters specified.\n## Usage :\n",argv[0]);
  595.     fprintf(stderr,"## -n -o ObjectName -t TypeName -z zoneName ## Shows network names\n");
  596.     fprintf(stderr,"## -s 1 | 0                                 ## Sets Self send flag\n");
  597.     fprintf(stderr,"## -d Net Node Socket ddpType [data]        ## Sends DDP packet\n");
  598.     fprintf(stderr,"## -e Net Node [Echo data]                     ## Sends Echo packet\n");
  599.     fprintf(stderr,"## -a Net Node Socket [UData] [data]        ## Sends ATPRequest\n");
  600.     fprintf(stderr,"## -r -o ObjectName -t TypeName             ## Registers Name\n");
  601.     fprintf(stderr,"## -z                                       ## Display zone names\n");
  602.     fprintf(stderr,"## © 1989 Apple Computer, Inc. by Ricardo Batista\n## Version 1.1\n\n");
  603. }
  604.  
  605.  
  606.  
  607.  
  608.  
  609.  
  610.  
  611.  
  612.  
  613.  
  614.  
  615.  
  616.  
  617.  
  618.  
  619.  
  620. void Names(int argc, char* argv[])
  621. {
  622.     AddrBlock address;
  623.     EntityName name;
  624.     short err, counter;
  625.     Handle buffer = 0L;
  626.     short found;
  627.     MPPParamBlock p;
  628.     char Entity[100];
  629.     
  630.     p.MPPioCompletion = 0L;
  631.     p.MPPioRefNum = mpp;
  632.     SpinCursor(1);
  633.     buffer = NewHandle(Buf);
  634.     if (!buffer) {
  635.         fprintf(stderr,"## %s: Not enough memory.\n",argv[0]);
  636.         return;
  637.     }
  638.     HLock(buffer);
  639.     name.objStr[1] = 0;
  640.     name.typeStr[1] = 0;
  641.     name.zoneStr[1] = 0;
  642.     name.objStr[0] = '=';
  643.     name.typeStr[0] = '=';
  644.     name.zoneStr[0] = '*';
  645.     for (counter = 2; counter < argc; counter++) {
  646.         if (argv[counter][0] == '-') {
  647.             if ((argv[counter][1] == 'o') || (argv[counter][1] == 'O')) {
  648.                 BlockMove(argv[counter + 1],name.objStr,33L);
  649.             }
  650.             if ((argv[counter][1] == 't') || (argv[counter][1] == 'T')) {
  651.                 BlockMove(argv[counter + 1],name.typeStr,33L);
  652.             }
  653.             if ((argv[counter][1] == 'z') || (argv[counter][1] == 'Z')) {
  654.                 BlockMove(argv[counter + 1],name.zoneStr,33L);
  655.             }
  656.         }
  657.     }
  658.     fprintf(stdout,"## %s: Network search for: '%s' '%s' '%s'\n\n\n",argv[0],name.objStr,name.typeStr,name.zoneStr);
  659.     fflush(stdout);
  660.     c2pstr(name.objStr);
  661.     c2pstr(name.typeStr);
  662.     c2pstr(name.zoneStr);
  663.     BlockMove(name.objStr,Entity,33L);
  664.     counter = Entity[0] + 1;
  665.     BlockMove(name.typeStr,&Entity[counter],33L);
  666.     counter += name.typeStr[0] + 1;
  667.     BlockMove(name.zoneStr,&Entity[counter],33L);
  668.     p.NBPinterval = 5;
  669.     p.NBPcount = 4;
  670.     p.NBPentityPtr = Entity;
  671.     p.NBPretBuffPtr = *buffer;
  672.     p.NBPretBuffSize = Buf;
  673.     p.NBPmaxToGet = Buf / 110;
  674.     err = PLookupName(&p,FALSE);
  675.     if (!err) {
  676.         while ((p.MPPioResult > 0) && !Abort())
  677.             SpinCursor(1);
  678.     }
  679.     err = p.MPPioResult;
  680.     if (!err) {
  681.         found = p.NBPnumGotten;
  682.         if (found > 1)
  683.             fprintf(stdout,"## %s: %d matches\n",argv[0],found);
  684.         if (found == 1)
  685.             fprintf(stdout,"## %s: %d match\n",argv[0],found);
  686.         if (found == 0)
  687.             fprintf(stdout,"## %s: No matches\n",argv[0]);
  688.         if (found) {
  689.             fprintf(stdout,"Object                    Type                      Zone                ");
  690.             fprintf(stdout,"Net    Node  Socket\n\n");
  691.         }
  692.         for (counter = 0; counter < found; counter++) {
  693.             address.aNet = 0;
  694.             err = myNBPExtract(*buffer,found,counter + 1,&name, &address);
  695.             p2cstr(name.objStr);
  696.             p2cstr(name.typeStr);
  697.             p2cstr(name.zoneStr);
  698.             fprintf(stdout,"%-25s %-25s %-20s",name.objStr,name.typeStr,name.zoneStr);
  699.             fprintf(stdout,"%-5u   %-5u %-5u\n",(unsigned short) address.aNet,address.aNode,address.aSocket);
  700.         }
  701.     }
  702.     fflush(stdout);
  703.     if (err)
  704.         fprintf(stderr,"err = %d\n",err);
  705.     if (buffer)
  706.         DisposHandle(buffer);
  707.     buffer = 0L;
  708. }
  709.  
  710.  
  711.  
  712.  
  713.  
  714.  
  715.  
  716.  
  717.  
  718.  
  719.  
  720.  
  721.  
  722.  
  723.  
  724.  
  725.  
  726. int myNBPExtract(buffer,howMany,which,Name,Addr)
  727. char *buffer;
  728. int howMany;
  729. int which;
  730. EntityName *Name;
  731. AddrBlock *Addr;
  732. {
  733.     char *p;
  734.     register int index = 1, nameCounter = 0;
  735.     
  736.     p = buffer;
  737.     while ((index < which) && (index < howMany)) {
  738.         p += 5;    /* skip addr and enumerator */
  739.         p += (*p) + 1;    /* skip name */
  740.         p += (*p) + 1;    /* skip type */
  741.         p += (*p) + 1;    /* skip zone */
  742.         index++;
  743.     }
  744.     BlockMove(p,(Ptr) Addr,4L);
  745.     p += 5;
  746.     BlockMove(p,Name->objStr,33L);
  747.     p += (*p) + 1;
  748.     BlockMove(p,Name->typeStr,33L);
  749.     p += (*p) + 1;
  750.     BlockMove(p,Name->zoneStr,33L);
  751.     return(0);
  752. }
  753.  
  754.  
  755.  
  756.  
  757.  
  758.  
  759.  
  760.  
  761.  
  762.  
  763.  
  764.  
  765.  
  766.  
  767.  
  768.  
  769. void DoZones(char* argv[])
  770. {
  771.     ATPParamBlock a;
  772.     short err = 0, counter;
  773.     short len;
  774.     char buffer[578];
  775.     BDSElement bds;
  776.     short abridge, node, net;
  777.     short howMany = 0, zones = 0;
  778.     char dummy[4];
  779.     long ourData;
  780.     Boolean done = FALSE;
  781.     short index;
  782.     char st[100];
  783.     
  784.     abridge = GetBridgeAddress();
  785.     if (!abridge) {
  786.         fprintf(stdout,"## %s: No zones in the network.\n\n",argv[0]);
  787.         return;
  788.     }
  789.     net = node = 0;
  790.     GetNodeAddress(&node,&net);
  791.     a.ATPioCompletion = 0L;
  792.     a.ATPatpSocket = 0;
  793.     a.ATPaddrBlock.aNet = net;
  794.     a.ATPaddrBlock.aNode = abridge;
  795.     a.ATPaddrBlock.aSocket = 6;
  796.     a.ATPuserData = GetZoneList;
  797.     a.ATPatpFlags = 0;
  798.     a.ATPreqLength = 0;
  799.     a.ATPreqPointer = 0L;
  800.     a.ATPnumOfBuffs = 1;
  801.     a.ATPtimeOutVal = 4;
  802.     a.ATPretryCount = 3;
  803.     a.ATPbdsPointer = (Ptr) &bds;
  804.     bds.buffSize = 600;
  805.     bds.buffPtr = &buffer[0];
  806.     bds.dataSize = 0;
  807.     bds.userBytes = 0L;
  808.     buffer[0] = 0;
  809.     ourData = 1;
  810.     fprintf(stdout,"\n## %s: Getting the zone names from a router....\n\n",argv[0]);
  811.     fflush(stdout);
  812.     while (!done) {
  813.         ourData |= GetZoneList;
  814.         a.ATPuserData = ourData;
  815.         err = PSendRequest(&a,TRUE);
  816.         while ((a.ATPioResult > 0) && !Abort())
  817.             SpinCursor(1);
  818.         err = a.ATPioResult;
  819.         if (err) {
  820.             fprintf(stderr,"## %s: Error requesting for zones %d\n",argv[0],err);
  821.             done = TRUE;
  822.             zones = 0;
  823.             if (err == 1)
  824.                 PKillSendReq(&a,false);
  825.         }
  826.         else {
  827.             BlockMove((Ptr) &(bds.userBytes),dummy,4L);
  828.             BlockMove(&dummy[2],(Ptr) &howMany,2L);
  829.             zones += howMany;
  830.             ourData = zones;
  831.             if (!done) {
  832.                 for (counter = 0, index = 0; counter < howMany; counter++) {
  833.                     len = buffer[index] + 1;
  834.                     BlockMove(&buffer[index],st,(long) len);
  835.                     p2cstr(st);
  836.                     fprintf(stdout,"## '%s'\n",st);
  837.                     index += len;
  838.                 }
  839.                 done = dummy[0];
  840.                 fflush(stdout);
  841.             }
  842.         }
  843.     }
  844.     if (zones) {
  845.         buffer[0] = 0;
  846.         a.ATPuserData = GetMyZone;
  847.         err = PSendRequest(&a,TRUE);
  848.         while ((a.ATPioResult > 0) && !Abort())
  849.             SpinCursor(1);
  850.         err = a.ATPioResult;
  851.         if (!err) {
  852.             p2cstr(buffer);
  853.             fprintf(stdout,"\n## %s: My zone is '%s'\n",argv[0],buffer);
  854.         }
  855.     }
  856.     fprintf(stdout,"\n\n");
  857. }